package com.zjitc.webSocket;

import com.google.gson.Gson;
import com.zjitc.pojo.ChatMessage;
import com.zjitc.pojo.User;


import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Create by IntelliJ IDEA
 *
 * @author: lhl
 * @date-Time: 2018/9/10 0010
 * @description:
 */
@ServerEndpoint(value = "/websocket", configurator = GetHttpSessionConfigurator.class)
public class WebSocketTest {
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
//    private static ApplicationContext ctx=null;
//    static {
//        ctx = new ClassPathXmlApplicationContext("classpath:spring-mybatis-config.xml");
//    }
    //    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
    private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
    private Session session;
    private Integer uid;
    private HttpSession httpSession;
//    //若要实现服务端与指定客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
    //Map不行，后期客户端下线，再次给下线的客户发信息，会报一些异常！
//    public static ConcurrentHashMap<Session,Object> webSocketMap = new ConcurrentHashMap<Session,Object>();

    public static ConcurrentHashMap<String, WebSocketTest> map = new ConcurrentHashMap<String, WebSocketTest>();

    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) throws InterruptedException, IOException {
        this.session = session;
        httpSession = (HttpSession) config.getUserProperties().get(
                HttpSession.class.getName());
       User user = (User) httpSession.getAttribute("user");
        System.out.println("自身打开webSocket" + user);
        this.uid=user.getId();
        webSocketSet.add(this);     //加入set中
        addOnlineCount();//在线数+1
        System.out.println("有新连接加入！当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message   客户端发送过来的消息
     * @param mySession 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session mySession) throws IOException, InterruptedException {
        System.out.println("来自客户端的消息:" + message);
        Gson gson=new Gson();
        ChatMessage chatMessage = gson.fromJson(message, ChatMessage.class);
        System.out.println("Json数据"+chatMessage);
        int acceptId=chatMessage.getAcceptId();
        for (WebSocketTest item : webSocketSet) {
            if (item.uid==acceptId){
                item.sendMessage(message);
            }
        }
    }
    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解，是根据自己需要添加的方法。
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        if (this.session != null) {
            this.session.getBasicRemote().sendText(message);
            //this.session.getAsyncRemote().sendText(message);
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketTest.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketTest.onlineCount--;
    }
}
